-module(echo_server).
%%--------------------------------------------------------------------
%% External exports
%%--------------------------------------------------------------------
-export([start/0]).

%%====================================================================
%% External functions
%%====================================================================
%%--------------------------------------------------------------------
%% @doc Start a new simple socket based Echo server.
%% @spec start() -> {ok, Pid} | {ok, Pid, State} | {error, Reason}
%% @end
%%--------------------------------------------------------------------
start() ->
    {ok, Listen} = gen_tcp:listen(2346, [binary, {packet, 0}, {reuseaddr, true}, {active, true}]), 
    spawn(fun() -> par_connect(Listen) end). 

%%====================================================================
%% Internal functions
%%====================================================================

%%--------------------------------------------------------------------
%% Support multiple concurrent connections by spawning new process on
%% each connection to the server socket.
%%--------------------------------------------------------------------
par_connect(Listen) -> 
    {ok, Socket} = gen_tcp:accept(Listen), 
    spawn(fun() -> par_connect(Listen) end), 
    loop(Socket). 

%%--------------------------------------------------------------------
%% Echo server main server loop.
%%--------------------------------------------------------------------
loop(Socket) ->
    receive
        {tcp, Socket, Bin} -> 
            io:fwrite("Server received binary = ~p~n",[Bin]), 
            case is_stop_cmd(Bin) of
                true -> 
                    io:fwrite("Server received BYE request.~n"),
                    gen_tcp:close(Socket);
                false ->  
                    gen_tcp:send(Socket, Bin), 
                    loop(Socket) 
            end;
        {tcp_closed, Socket} -> 
            io:fwrite("Server socket closed~n") 
    end.

%%--------------------------------------------------------------------
%% Test for BYE ascii string.
%%--------------------------------------------------------------------
is_bye_str("BYE") -> true;
is_bye_str(_Any) -> false.

%%--------------------------------------------------------------------
%% Simple function to strip carriage returns and line feed characters.
%%--------------------------------------------------------------------
strip([]) -> [];
strip([10]) -> [];
strip([13]) -> [];
strip([13 | T]) -> strip(T);
strip([10 | T]) -> strip(T);
strip([H | T]) -> [H | strip(T)].

%%--------------------------------------------------------------------
%% Test if binary is BYE ascii string. 
%%--------------------------------------------------------------------
is_stop_cmd(Bin) ->
    List = binary_to_list(Bin),
    Str = strip(List),
    is_bye_str(Str).
